<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>Docs重构 | Blog</title>
    <meta name="generator" content="VuePress 1.9.10">
    <link rel="icon" href="/blog/img/logo.png">
    <link rel="manifest" href="/blog/manifest.json">
    <link rel="apple-touch-icon" href="/blog/icons/apple-touch-icon-152x152.png">
    <link rel="mask-icon" href="/blog/icons/safari-pinned-tab.svg" color="#3eaf7c">
    <meta name="description" content="blog | js | node | vue | vuepress | webpack">
    <meta name="theme-color" content="#3eaf7c">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="msapplication-TileImage" content="/icons/msapplication-icon-144x144.png">
    <meta name="msapplication-TileColor" content="#000000">
    
    <link rel="preload" href="/blog/assets/css/0.styles.b6b82f87.css" as="style"><link rel="preload" href="/blog/assets/js/app.1f72a262.js" as="script"><link rel="preload" href="/blog/assets/js/2.d3a12b6d.js" as="script"><link rel="preload" href="/blog/assets/js/1.f8bb34da.js" as="script"><link rel="preload" href="/blog/assets/js/29.4c491e42.js" as="script"><link rel="prefetch" href="/blog/assets/js/10.fde088a2.js"><link rel="prefetch" href="/blog/assets/js/11.c62b6b34.js"><link rel="prefetch" href="/blog/assets/js/12.27d4f152.js"><link rel="prefetch" href="/blog/assets/js/13.419d7748.js"><link rel="prefetch" href="/blog/assets/js/14.eb7a3d07.js"><link rel="prefetch" href="/blog/assets/js/15.114dfd5c.js"><link rel="prefetch" href="/blog/assets/js/16.85253907.js"><link rel="prefetch" href="/blog/assets/js/17.c2838453.js"><link rel="prefetch" href="/blog/assets/js/18.3256f17f.js"><link rel="prefetch" href="/blog/assets/js/19.d8afd0ae.js"><link rel="prefetch" href="/blog/assets/js/20.0d880388.js"><link rel="prefetch" href="/blog/assets/js/21.33b300c9.js"><link rel="prefetch" href="/blog/assets/js/22.2901c590.js"><link rel="prefetch" href="/blog/assets/js/23.b74cc977.js"><link rel="prefetch" href="/blog/assets/js/24.e7339d1a.js"><link rel="prefetch" href="/blog/assets/js/25.ca9a652b.js"><link rel="prefetch" href="/blog/assets/js/26.486b2b13.js"><link rel="prefetch" href="/blog/assets/js/27.1884e308.js"><link rel="prefetch" href="/blog/assets/js/28.276df742.js"><link rel="prefetch" href="/blog/assets/js/3.af33e5d6.js"><link rel="prefetch" href="/blog/assets/js/30.20482e57.js"><link rel="prefetch" href="/blog/assets/js/31.75f2ce85.js"><link rel="prefetch" href="/blog/assets/js/32.44f43246.js"><link rel="prefetch" href="/blog/assets/js/33.2996c854.js"><link rel="prefetch" href="/blog/assets/js/34.2ad07be7.js"><link rel="prefetch" href="/blog/assets/js/35.33a7e89c.js"><link rel="prefetch" href="/blog/assets/js/36.b852c680.js"><link rel="prefetch" href="/blog/assets/js/37.899a12b5.js"><link rel="prefetch" href="/blog/assets/js/38.162f5233.js"><link rel="prefetch" href="/blog/assets/js/39.c65fce7b.js"><link rel="prefetch" href="/blog/assets/js/4.0a92875f.js"><link rel="prefetch" href="/blog/assets/js/40.7c1b09b5.js"><link rel="prefetch" href="/blog/assets/js/41.9d3ac8ff.js"><link rel="prefetch" href="/blog/assets/js/42.cd05e187.js"><link rel="prefetch" href="/blog/assets/js/43.397664c2.js"><link rel="prefetch" href="/blog/assets/js/44.0bd439fc.js"><link rel="prefetch" href="/blog/assets/js/45.8230a2d9.js"><link rel="prefetch" href="/blog/assets/js/46.037916dd.js"><link rel="prefetch" href="/blog/assets/js/47.c6fb17e0.js"><link rel="prefetch" href="/blog/assets/js/48.4407ce14.js"><link rel="prefetch" href="/blog/assets/js/49.3881911f.js"><link rel="prefetch" href="/blog/assets/js/5.3b9be48d.js"><link rel="prefetch" href="/blog/assets/js/50.ddcdd5d1.js"><link rel="prefetch" href="/blog/assets/js/51.ae4c3ad2.js"><link rel="prefetch" href="/blog/assets/js/52.0bedd932.js"><link rel="prefetch" href="/blog/assets/js/53.36145b4b.js"><link rel="prefetch" href="/blog/assets/js/54.7cefd728.js"><link rel="prefetch" href="/blog/assets/js/55.d7838999.js"><link rel="prefetch" href="/blog/assets/js/56.fd91fbf0.js"><link rel="prefetch" href="/blog/assets/js/57.5f4eb38a.js"><link rel="prefetch" href="/blog/assets/js/58.db550faf.js"><link rel="prefetch" href="/blog/assets/js/59.e6de6dee.js"><link rel="prefetch" href="/blog/assets/js/6.7b96ebf4.js"><link rel="prefetch" href="/blog/assets/js/60.7d9a1afb.js"><link rel="prefetch" href="/blog/assets/js/61.fff94771.js"><link rel="prefetch" href="/blog/assets/js/62.74513aaa.js"><link rel="prefetch" href="/blog/assets/js/63.111aab67.js"><link rel="prefetch" href="/blog/assets/js/64.b0b6c26f.js"><link rel="prefetch" href="/blog/assets/js/65.65aade87.js"><link rel="prefetch" href="/blog/assets/js/66.a13d5c25.js"><link rel="prefetch" href="/blog/assets/js/7.7e58b9c4.js"><link rel="prefetch" href="/blog/assets/js/vendors~docsearch.2493936b.js">
    <link rel="stylesheet" href="/blog/assets/css/0.styles.b6b82f87.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/blog/" class="home-link router-link-active"><!----> <span class="site-name">Blog</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/blog/" class="nav-link">
  home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="long-ui" class="dropdown-title"><span class="title">long-ui</span> <span class="arrow down"></span></button> <button type="button" aria-label="long-ui" class="mobile-dropdown-title"><span class="title">long-ui</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/ui/" class="nav-link">
  UI简介
</a></li><li class="dropdown-item"><!----> <a href="https://weberlong.github.io/long-ui/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  预览
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/WeberLong/long-ui" target="_blank" rel="noopener noreferrer" class="nav-link external">
  源码
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="/blog/archives/" class="nav-link router-link-active">
  archives
</a></div><div class="nav-item"><a href="/blog/interview/" class="nav-link">
  interview
</a></div> <a href="https://github.com/WeberLong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="/blog/" class="nav-link">
  home
</a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="long-ui" class="dropdown-title"><span class="title">long-ui</span> <span class="arrow down"></span></button> <button type="button" aria-label="long-ui" class="mobile-dropdown-title"><span class="title">long-ui</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/blog/ui/" class="nav-link">
  UI简介
</a></li><li class="dropdown-item"><!----> <a href="https://weberlong.github.io/long-ui/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  预览
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://github.com/WeberLong/long-ui" target="_blank" rel="noopener noreferrer" class="nav-link external">
  源码
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><a href="/blog/archives/" class="nav-link router-link-active">
  archives
</a></div><div class="nav-item"><a href="/blog/interview/" class="nav-link">
  interview
</a></div> <a href="https://github.com/WeberLong" target="_blank" rel="noopener noreferrer" class="repo-link">
    GitHub
    <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></nav>  <ul class="sidebar-links"><li><section class="sidebar-group depth-0"><a href="/blog/archives/" class="sidebar-heading clickable router-link-active open"><span>我的文章</span> <!----></a> <ul class="sidebar-links sidebar-group-items"><li><a href="/blog/archives/component.html" class="sidebar-link">Vue组件开发</a></li><li><a href="/blog/archives/webpack.html" class="sidebar-link">Webpack简介</a></li><li><a href="/blog/archives/rtlcss.html" class="sidebar-link">阿拉伯语右排布局</a></li><li><a href="/blog/archives/monitor.html" class="sidebar-link">性能与错误监控方案</a></li><li><a href="/blog/archives/performance.html" class="sidebar-link">前端性能优化</a></li><li><a href="/blog/archives/recode.html" aria-current="page" class="active sidebar-link">Docs重构</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#一、背景" class="sidebar-link">一、背景</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_1-巨石应用维护困难" class="sidebar-link">1. 巨石应用维护困难</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_2-开发流程复杂" class="sidebar-link">2. 开发流程复杂</a></li></ul></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#二、微前端" class="sidebar-link">二、微前端</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_1-什么是微前端" class="sidebar-link">1. 什么是微前端</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_2-微前端优势" class="sidebar-link">2. 微前端优势</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_3-微前端框架选择" class="sidebar-link">3. 微前端框架选择</a></li></ul></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#三、qiankun" class="sidebar-link">三、qiankun</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#四、qiankun实战" class="sidebar-link">四、qiankun实战</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_1-创建基座" class="sidebar-link">1. 创建基座</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_2-创建微应用" class="sidebar-link">2. 创建微应用</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_3-项目结构" class="sidebar-link">3. 项目结构</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_4-功能演示" class="sidebar-link">4. 功能演示</a></li></ul></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#五、qiankun接入docs" class="sidebar-link">五、qiankun接入Docs</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_1-接入要点" class="sidebar-link">1. 接入要点</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_2-技术架构" class="sidebar-link">2. 技术架构</a></li><li class="sidebar-sub-header"><a href="/blog/archives/recode.html#_3-docs微前端" class="sidebar-link">3. Docs微前端</a></li></ul></li></ul></li><li><a href="/blog/archives/cach.html" class="sidebar-link">理解浏览器缓存</a></li><li><a href="/blog/archives/httpcode.html" class="sidebar-link">HTTP 状态码</a></li></ul></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="docs重构"><a href="#docs重构" class="header-anchor">#</a> Docs重构</h1> <h2 id="一、背景"><a href="#一、背景" class="header-anchor">#</a> 一、背景</h2> <p>Docs项目有以下几点主要痛点：</p> <h3 id="_1-巨石应用维护困难"><a href="#_1-巨石应用维护困难" class="header-anchor">#</a> 1. 巨石应用维护困难</h3> <p>金山文档经过多年持续不断的迭代，已经变得很庞大，项目本地打包耗时30分钟，打包后的主文件vendor.js有7M，kso-ui.js有6.3M，部署上线要耗费大半天时间，头一回遇到这种巨石应用。</p> <h3 id="_2-开发流程复杂"><a href="#_2-开发流程复杂" class="header-anchor">#</a> 2. 开发流程复杂</h3> <p>无法本地运行开发，遇到复杂需求和bug需要反复修改和反复部署，效率非常低。例如：修改kso里面的bug，改kso代码 -&gt; 私有化(jenkins) -&gt; kso发包 -&gt; cloud/mobile私有化 -&gt; 部署，整个流程走完大概2个小时。</p> <img src="/blog/img/recode_01.png"> <h2 id="二、微前端"><a href="#二、微前端" class="header-anchor">#</a> 二、微前端</h2> <p>微前端的诞生也是为了解决以上问题。</p> <h3 id="_1-什么是微前端"><a href="#_1-什么是微前端" class="header-anchor">#</a> 1. 什么是微前端</h3> <p>微前端是一种类似于微服务的架构，它将微服务的理念应用于浏览器端，即将 Web 应用由单一的单体应用转变为 <strong>多个小型前端应用聚合为一的应用</strong> 。各个前端应用还可以 <strong>独立运行、独立开发、独立部署</strong> 。</p> <h3 id="_2-微前端优势"><a href="#_2-微前端优势" class="header-anchor">#</a> 2. 微前端优势</h3> <ul><li><strong>复杂度可控</strong>** 😗* 每一个UI业务模块由独立的前端团队开发，避免代码巨无霸，保持开发时的高速编译，保持较低的复杂度，便于维护与开发效率。</li> <li><strong>独立部署</strong>** 😗* 每一个模块可单独部署，颗粒度可小到单个组件的UI独立部署，不对其他模块有任何影响。</li> <li><strong>技术选型灵活</strong>** 😗*也是最具吸引力的，在同一项目下可以使用如今市面上所有前端技术栈vue/react/angular/jquery...</li> <li><strong>扩展</strong>** 😗* 每一个服务可以独立横向扩展以满足业务伸缩性。</li> <li><strong>容错</strong>** 😗* 单个模块发生错误，不影响全局，就跟后端微服务一样。</li></ul> <h3 id="_3-微前端框架选择"><a href="#_3-微前端框架选择" class="header-anchor">#</a> 3. 微前端框架选择</h3> <p>调研了市面上实现微前端的框架，可供选择的有iframe、sigle-spa、qiankun和microApp。single-spa太过于基础，对原有项目的改造过多，成本太高，对项目的可维护性带来了挑战； iframe在所有微前端方案中是最稳定的、上手难度最低的，但它有一些无法解决的问题，例如性能低、通信复杂、双滚动条、弹窗无法全局覆盖，它的成长性不高，只适合简单的页面渲染。剩下的只有qiankun和microApp了。microApp是基于WebComponent进行渲染的，如果嵌入到PC客户端里兼容性有问题，最后只剩下qiankun。</p> <img src="/blog/img/recode_02.png"> <h2 id="三、qiankun"><a href="#三、qiankun" class="header-anchor">#</a> 三、qiankun</h2> <p><a href="https://qiankun.umijs.org/zh" target="_blank" rel="noopener noreferrer">qiankun<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>框架其实是基于single-spa框架搭建而成的，本质上是把 single-spa 和 import-html-entry 整合在了一起，简单来说就是single-spa的优化版。</p> <p><em>qiankun</em> <em>是一个基于</em> <em>single-spa</em> <em>的微前端实现库，旨在帮助大家能更简单、无痛的构建一个生产可用微前端架构系统。</em> <em>qiankun</em> <em>孵化自蚂蚁金融科技基于微前端架构的云产品统一接入平台，在经过一批线上应用的充分检验及打磨后，我们将其微前端内核抽取出来并开源，希望能同时帮助社区有类似需求的系统更方便的构建自己的微前端系统，同时也希望通过社区的帮助将</em> <em>qiankun</em> <em>打磨的更加成熟完善。 目前</em> <em>qiankun</em> <em>已在蚂蚁内部服务了超过</em> <em>200+</em> <em>线上应用，在易用性及完备性上，绝对是值得信赖的。</em> <em>---- <strong>摘自</strong> qiankun__官网介绍</em></p> <img src="/blog/img/recode_03.png"> <h2 id="四、qiankun实战"><a href="#四、qiankun实战" class="header-anchor">#</a> 四、qiankun实战</h2> <p>qiankun架构基本可以概括为: 基座应用 + 子应用 + 公共依赖方式，详细架构如下图：</p> <img src="/blog/img/recode_04.png"> <h3 id="_1-创建基座"><a href="#_1-创建基座" class="header-anchor">#</a> 1. 创建基座</h3> <p>初始化基座项目，通过vue-cli快速创建一个vue项目</p> <div class="language-js extra-class"><pre class="language-js"><code>vue create appmain
</code></pre></div><p>构建主应用基座，开始进行改造，首先安装qiankun</p> <div class="language-js extra-class"><pre class="language-js"><code>yarn add qiankun
</code></pre></div><p>安装完qiankun后，先对main.ts进行改造，针对主应用进行配置，这里我们需要定义并注册微服务应用，并添加全局状态管理与消息通知机制，apps.ts文件用于统一存放微应用的信息，微应用配置信息中的container是用于设定微应用挂载节点的，要与自己设定的节点&lt;div id=&quot;subapp&quot;&gt;&lt;/div&gt;中的id保持一致。</p> <p>main.ts的改造过程:</p> <ol><li>初始化基座应用 vue create main；</li> <li>安装乾坤 yarn add qiankun；</li> <li>设置微服务应用挂载的DOM节点，注意这个id需要在注册子应用时使用；</li> <li>定义子应用 main\src\core\apps.ts；</li> <li>改造main.ts，注册子应用并添加相关工具类函数。</li></ol> <p>接下来就是需要定义子应用，并确保定义的子应用能在当前基座应用下成功运行。</p> <h3 id="_2-创建微应用"><a href="#_2-创建微应用" class="header-anchor">#</a> 2. 创建微应用</h3> <p>接入Vue子应用app1(vue3)</p> <div class="language-js extra-class"><pre class="language-js"><code>vue create app1
</code></pre></div><p>添加vue.config.js，有两点需要注意：</p> <ul><li>output需要设置为umd格式的library，这样主应用就可以加载当前lib并运行。</li> <li>devServe端口需要设置与注册该子应用时的端口一致, 并设置cors, 因为子应用与主应用不同域。</li></ul> <p>改造子应用的main.ts。子应用的接入需要符合qiankun的接入协议，子应用不需要额外安装任何其它依赖即可接入主应用。</p> <p>其他微应用配置同上。</p> <h3 id="_3-项目结构"><a href="#_3-项目结构" class="header-anchor">#</a> 3. 项目结构</h3> <div class="language-bash extra-class"><pre class="language-bash"><code>qiankunapp
├─ app1
├─ app2
├─ app3
├─ app4
├─ app5
└─ appmain
</code></pre></div><h3 id="_4-功能演示"><a href="#_4-功能演示" class="header-anchor">#</a> 4. 功能演示</h3> <img src="/blog/img/recode_05.png"> <h2 id="五、qiankun接入docs"><a href="#五、qiankun接入docs" class="header-anchor">#</a> 五、qiankun接入Docs</h2> <h3 id="_1-接入要点"><a href="#_1-接入要点" class="header-anchor">#</a> 1. 接入要点</h3> <ul><li><strong>动态路由管理</strong></li></ul> <p>使子工程之间有能力互通切换，以路由为单位把新旧模块逐步替换。</p> <img src="/blog/img/recode_06.png"> <ul><li><strong>全局状态管理</strong></li></ul> <p>qiankun通过initGlobalState, onGlobalStateChange, setGlobalState实现主应用的全局状态管理，然后默认会通过props将通信方法传递给子应用。官方示例用法：</p> <p>主应用：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// main/src/main.js</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span> initGlobalState <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'qiankun'</span><span class="token punctuation">;</span>
<span class="token comment">// 初始化 state</span>
<span class="token keyword">const</span> initialState <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token literal-property property">user</span><span class="token operator">:</span> <span class="token punctuation">{</span><span class="token punctuation">}</span> <span class="token comment">// 用户信息</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> actions <span class="token operator">=</span> <span class="token function">initGlobalState</span><span class="token punctuation">(</span>initialState<span class="token punctuation">)</span><span class="token punctuation">;</span>
actions<span class="token punctuation">.</span><span class="token function">onGlobalStateChange</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> prev</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token comment">// state: 变更后的状态; prev 变更前的状态</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> prev<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
actions<span class="token punctuation">.</span><span class="token function">setGlobalState</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span><span class="token punctuation">;</span>
actions<span class="token punctuation">.</span><span class="token function">offGlobalStateChange</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>子应用：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 从生命周期 mount 中获取通信方法，props默认会有onGlobalStateChange和setGlobalState两个api</span>
<span class="token keyword">export</span> <span class="token keyword">function</span> <span class="token function">mount</span><span class="token punctuation">(</span><span class="token parameter">props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  props<span class="token punctuation">.</span><span class="token function">onGlobalStateChange</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">state<span class="token punctuation">,</span> prev</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
    <span class="token comment">// state: 变更后的状态; prev 变更前的状态</span>
    console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>state<span class="token punctuation">,</span> prev<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  props<span class="token punctuation">.</span><span class="token function">setGlobalState</span><span class="token punctuation">(</span>state<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>父子应用通过onGlobalStateChange这个方法进行通信，其实是发布-订阅模式。</p> <h3 id="_2-技术架构"><a href="#_2-技术架构" class="header-anchor">#</a> 2. 技术架构</h3> <p>qiankun：基座nuxt.js(ssr) + 微应用vue/react</p> <p>详细架构图如下：</p> <img src="/blog/img/recode_07.png"> <h3 id="_3-docs微前端"><a href="#_3-docs微前端" class="header-anchor">#</a> 3. Docs微前端</h3> <p>Docs微前端设计图如下：</p> <img src="/blog/img/recode_08.png"></div> <footer class="page-edit"><!----> <!----></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/blog/archives/performance.html" class="prev">
        前端性能优化
      </a></span> <span class="next"><a href="/blog/archives/cach.html">
        理解浏览器缓存
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"></div></div>
    <script src="/blog/assets/js/app.1f72a262.js" defer></script><script src="/blog/assets/js/2.d3a12b6d.js" defer></script><script src="/blog/assets/js/1.f8bb34da.js" defer></script><script src="/blog/assets/js/29.4c491e42.js" defer></script>
  </body>
</html>
